package com.qqs.distributed.advice;

import com.qqs.distributed.cache.CacheHandler;
import com.qqs.distributed.cache.CacheHandlerWrapper;
import com.qqs.distributed.lock.LockHandler;
import org.aopalliance.intercept.MethodInvocation;
import org.redisson.api.RBloomFilter;


import java.util.Objects;

import static com.qqs.distributed.advice.AbstractCacheInterceptor.NULL_BLOOM_FILTER;

public class DefaultCacheHandlerAdapter implements CacheHandlerAdapter {
    private LockHandler lockHandler;
    private CacheHandler cacheHandler;
    private CacheAttributeWrapper attributeWrapper;
    private RBloomFilter bloomFilter;
    private MethodInvocation invocation;

    public DefaultCacheHandlerAdapter(LockHandler lockHandler,
                                      CacheHandler cacheHandler,
                                      CacheAttributeWrapper attributeWrapper,
                                      RBloomFilter bloomFilter, MethodInvocation invocation) {
        this.lockHandler = lockHandler;
        this.cacheHandler = cacheHandler;
        this.attributeWrapper = attributeWrapper;
        this.bloomFilter = bloomFilter;
        this.invocation = invocation;
    }

    /**
     * TODO 布隆过滤器逻辑待实现
     *
     * @return
     */
    @Override
    public Object handle() throws Throwable {

        // 检查布隆过滤器
        if (!NULL_BLOOM_FILTER.equals(bloomFilter) && !bloomFilter.contains(attributeWrapper.getKey())) {
            return null;
        }

        // 检查缓存中是否存在
        CacheHandlerWrapper handlerWrapper = new CacheHandlerWrapper(cacheHandler, attributeWrapper);
        Object res = handlerWrapper.query();
        if (!Objects.isNull(res)) {
            return res;
        }
        try {
            // 上锁
            lockHandler.lock();
            // 再次检查缓存中是否存在
            res = handlerWrapper.query();
            if (!Objects.isNull(res)) {
                return res;
            }
            res = invocation.proceed();
            // CacheHandler自己解决缓存穿透问题
            handlerWrapper.save(res);
            return res;
        } finally {
            // 解锁
            lockHandler.unlock();
        }
    }
}
